#pragma once

#include "liblegerber_global.h"

#include <QtMath>
#include <QObject>
#include <QMap>
#include <QMultiMap>
#include <QPointF>

#include "gerber.h"
#include "statement.h"

namespace LeGerber
{

	class Command;

	class LEGERBER_EXPORT FileReaderContext
	{
	public:
		FileReaderContext()
		{
			update();
		}

		CoordinateNotation coordinateNotation = InvalidCoordinateNotation;
		ZeroBehaviour zeroBehaviour = InvalidZeroBehaviour;

		int coordinateIntegralDigits = 2;
		int coordinateFractionalDigits = 5;

		QPointF readCoordinate(const QString &x, const QString &y) const;
		qreal readCoordinateNumber(const QString &str) const;
		void clear();
		void update()
		{
			coordinateDivider = qPow(10.0, -coordinateFractionalDigits);
		}
		qreal coordinateDivider;
	};

	// See as well: https://github.com/curtacircuitos/pcb-tools/blob/master/gerber/rs274x.py
	class LEGERBER_EXPORT FileReader : public QObject
	{
		Q_OBJECT
	public:

		explicit FileReader(QObject *parent = 0);
		~FileReader();

		void setData(const QByteArray &data);

		bool parse();

		bool isValid() const;
		QString errorString() const;
		int errorLocation() const;

		int warningCount() const;
		QStringList warnings() const;

		int codeCount() const;
		GerberCodeStatistics codeStatistics() const;
		void clearStatisitics();

		int commandCount() const;
		QList<Command*> takeCommands();

		CoordinateNotation coordinateNotation() const;
		ZeroBehaviour zeroBehaviour() const;
		int coordinateIntegralDigits() const;
		int coordinateFractionalDigits() const;
		qreal coordinateDivider() const;

		QList<Statement> statements() const;
		QString statementText(int start, int length) const;

	public slots:

	private:
		bool handleLegacyStatement(int length, int start);
		bool parseXYIJ(int start, int length, QPointF &xy, QPointF &ij);
		bool handleExtentedStatement(int start, int length);
		bool handleGarbage(int start, int end);

		QByteArray m_data;

		void clearErrorAndWarnings();
		void setError(int offset, const QString &message);
		void addWarning(int offset, const QString &message);
		QPair<int, QString> m_error;
		QMultiMap<int, QString> m_warnings;

		void clearCommands();
		QList<Command*> m_commands;

		void clearContext();
		FileReaderContext m_context;

		void clearStatements();
		QList<Statement> m_statements;

		GerberCodeStatistics m_codeStats;
	};

}